/*
    This source file is part of GeNa project.
    Copyright © GeNa project 2008
    For the latest info, see http://code.google.com/p/genaproject/ or  http://lumpyproject.forums-rpg.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef VERTEXDECL_H_INCLUDED
#define VERTEXDECL_H_INCLUDED

#include <vector>
#include <algorithm>
#include <string>

class VertexElement
{
public:
    std::string name;

    GLenum type; //Either GL_SHORT, GL_INT, GL_FLOAT, OR GL_DOUBLE
    int numComponents;
    bool normalized;

    int pos;
    int buffer;

    int firstElem;
    int stride;

    bool operator<(const VertexElement &elem)
    {
        if( pos < elem.pos)
            return true;
        return false;
    }

//    template<class T> GLenum getGLType()
//    {
//        return 0;
//    }

    template<class T> T* get(int index, void* buf)
    {
        return (T*)((unsigned int)buf + firstElem + index*stride);
    }

    bool linkAttribute(int index)
    {
        if( index == -1)
            return true;

        glEnableVertexAttribArray(index);
        glVertexAttribPointer(index, numComponents, type, normalized, stride, (void*)firstElem);
        return true;
    }
};


//template<> GLenum VertexElement::getGLType<short>()
//{
//    return GL_SHORT;
//}
//
//template<> GLenum VertexElement::getGLType<int>()
//{
//    return GL_INT;
//}
//
//template<> GLenum VertexElement::getGLType<float>()
//{
//    return GL_FLOAT;
//}
//
//template<> GLenum VertexElement::getGLType<double>()
//{
//    return GL_DOUBLE;
//}

class VertexDeclaration
{
public:
    std::vector<VertexElement*> elems;
    unsigned int size;

    void update()
    {
        //std::sort( elems.begin(), elems.end());
        size = 0;
        int pos = -1;
        for( unsigned int i=0; i < elems.size(); i++)
        {
            elems[i]->firstElem = size;
            if( elems[i]->pos != pos)
            {
                switch( elems[i]->type)
                {
                    case GL_SHORT:
                        size += 2*elems[i]->numComponents;
                        break;
                    case GL_INT:
                    case GL_FLOAT:
                        size += 4*elems[i]->numComponents;
                        break;
                    case GL_DOUBLE:
                        size += 8*elems[i]->numComponents;
                        break;
                }
            }
        }

        for( unsigned int i=0; i < elems.size(); i++)
            elems[i]->stride = size;
    }
};

#endif // VERTEXDECL_H_INCLUDED
